﻿Imports System
Imports System.Collections.Generic
Imports System.Diagnostics
Imports System.Workflow.ComponentModel
Imports System.Workflow.Runtime

Namespace System.Workflow.Activities
    <Serializable> _
    Friend NotInheritable Class CorrelationTokenInvalidatedHandler
        Implements IActivityEventListener([Of] CorrelationTokenEventArgs)
        ' Methods
        Friend Sub New(ByVal interfaceType As Type, ByVal operation As String, ByVal eventHandler As IActivityEventListener([Of] QueueEventArgs), ByVal instanceId As Guid)
            Me.eventHandler = eventHandler
            Me.interfaceType = interfaceType
            Me.followerOperation = operation
            Me.instanceId = instanceId
        End Sub

        Private Sub CreateSubscription(ByVal instanceId As Guid, ByVal context As ActivityExecutionContext, ByVal correlationValues As ICollection([Of] CorrelationProperty))
            Dim service As WorkflowQueuingService = context.GetService([Of] WorkflowQueuingService)
            Dim queueName As New EventQueueName(Me.interfaceType, Me.followerOperation, correlationValues)
            Dim workflowQueue As WorkflowQueue = Nothing
            If Not service.Exists(queueName) Then
                WorkflowActivityTrace.Activity.TraceEvent(TraceEventType.Information, 0, "CorrelationTokenInvalidatedHandler: creating q {0} ", New Object() { queueName.GetHashCode })
                workflowQueue = service.CreateWorkflowQueue(queueName, True)
                Me.queueCreator = True
            Else
                workflowQueue = service.GetWorkflowQueue(queueName)
            End If
            If (Not Me.eventHandler Is Nothing) Then
                workflowQueue.RegisterForQueueItemAvailable(Me.eventHandler)
            End If
            Dim service2 As WorkflowSubscriptionService = DirectCast(context.GetService(GetType(WorkflowSubscriptionService)), WorkflowSubscriptionService)
            Dim subscription As New MessageEventSubscription(queueName, instanceId)
            Me.queueName = queueName
            Me.subscriptionId = subscription.SubscriptionId
            subscription.InterfaceType = Me.interfaceType
            subscription.MethodName = Me.followerOperation
            Me.interfaceType = Nothing
            Me.followerOperation = Nothing
            If (Not correlationValues Is Nothing) Then
                Dim property As CorrelationProperty
                For Each property In correlationValues
                    subscription.CorrelationProperties.Add([property])
                Next
            End If
            If ((Me.eventHandler Is Nothing) AndAlso (Not service2 Is Nothing)) Then
                service2.CreateSubscription(subscription)
            End If
        End Sub

        Private Sub DeleteSubscription(ByVal context As ActivityExecutionContext)
            If (Not Me.queueName Is Nothing) Then
                Dim service As WorkflowQueuingService = context.GetService([Of] WorkflowQueuingService)
                If Me.queueCreator Then
                    service.DeleteWorkflowQueue(Me.queueName)
                End If
                If (Me.eventHandler Is Nothing) Then
                    Dim service2 As WorkflowSubscriptionService = context.GetService([Of] WorkflowSubscriptionService)
                    If (Not service2 Is Nothing) Then
                        service2.DeleteSubscription(Me.subscriptionId)
                    End If
                    WorkflowActivityTrace.Activity.TraceEvent(TraceEventType.Information, 0, "CorrelationTokenInvalidatedHandler subscription deleted SubId {0} QueueId {1}", New Object() { Me.subscriptionId, Me.queueName })
                End If
            End If
        End Sub

        Private Sub System.Workflow.ComponentModel.IActivityEventListener<System.Workflow.Runtime.CorrelationTokenEventArgs>.OnEvent(ByVal sender As Object, ByVal dataChangeEventArgs As CorrelationTokenEventArgs) Implements IActivityEventListener([Of] CorrelationTokenEventArgs).OnEvent
            If (sender Is Nothing) Then
                Throw New ArgumentException("sender")
            End If
            If (dataChangeEventArgs Is Nothing) Then
                Throw New ArgumentException("dataChangeEventArgs")
            End If
            Dim context As ActivityExecutionContext = [TryCast](sender,ActivityExecutionContext)
            Dim activity As Activity = context.Activity
            Dim properties As ICollection([Of] CorrelationProperty) = dataChangeEventArgs.CorrelationToken.Properties
            If dataChangeEventArgs.IsInitializing Then
                Me.CreateSubscription(Me.instanceId, context, properties)
            Else
                If ((Not Me.queueName Is Nothing) AndAlso Not CorrelationResolver.IsInitializingMember(Me.queueName.InterfaceType, Me.queueName.MethodName, If((properties Is Nothing), Nothing, New Object() { properties }))) Then
                    Me.DeleteSubscription(context)
                End If
                dataChangeEventArgs.CorrelationToken.UnsubscribeFromCorrelationTokenInitializedEvent(activity, Me)
            End If
        End Sub


        ' Fields
        Private eventHandler As IActivityEventListener([Of] QueueEventArgs)
        Private followerOperation As String
        Private instanceId As Guid
        Private interfaceType As Type
        Private queueCreator As Boolean
        Private queueName As EventQueueName
        Private subscriptionId As Guid
    End Class
End Namespace

